﻿#include "CELLClient.h"

#include "CELL.h"
#include "CELLObjectPool.hpp"
#include "CELLNetWork.hpp"
#include <memory>
#include <string.h>
#include "CELLBuffer.h"

// 客户端心跳检测死亡计时时间 10秒钟（单位：毫秒）
#define CLIENT_HEART_DEAD_TIME 10000
// 指定时间内清空发送缓冲区(清空指发送)
#define CLIENT_SEND_BUF_TIME 200

CELLClient::CELLClient(SOCKET sock, int sendSize, int recvSize)
	: _sockfd(sock), _sendBuff(sendSize), _recvBuff(recvSize)
{
	static int n = 1;
	id = n++;
	// 初始化客户端的时候死亡倒计时清0
	resetDtHeart();
	// 初始化客户端上次发送消息时间
	resetDtSend();
}

CELLClient::~CELLClient()
{
	CELLLog_Debug("CELLClient %d ~CELLClient", id);
	destory();
}

void CELLClient::destory()
{
	// 将socket关闭
	if (_sockfd != INVALID_SOCKET)
	{
		CELLLog_Debug("CELLClient %d destory", id);
		CELLNetWork::destorySocket(_sockfd);
		_sockfd = INVALID_SOCKET;
	}
}

SOCKET CELLClient::sockfd()
{
	return _sockfd;
}

// 发回数据
int CELLClient::SendData(DataHeader* header)
{
	return SendData((const char*)header, header->dataLength);
}

int CELLClient::SendData(const char* pData, int len)
{
	if (_sendBuff.push(pData, len))
	{
		return len;
	}
	return SOCKET_ERROR;
}

// 立即发送缓冲区的数据
int CELLClient::SendDataReal()
{
	resetDtSend();
	return _sendBuff.write2socket(_sockfd);
}

// 接收数据
int CELLClient::RecvData()
{
	return _recvBuff.read4socket(_sockfd);
}

// 有无消息
bool CELLClient::hasMsg()
{
	return _recvBuff.hasMsg();
}

// 发送缓冲区是否有数据需要发送
bool CELLClient::needWrite()
{
	return _sendBuff.needWrite();
}

// 得到第一条消息
DataHeader* CELLClient::front_msg()
{
	return (DataHeader*)_recvBuff.data();
}

// 删除最前面一条消息
void CELLClient::pop_front_msg()
{
	if (hasMsg())
		_recvBuff.pop(front_msg()->dataLength);
}

// 把心跳计时置0
void CELLClient::resetDtHeart()
{
	_dtHeart = 0;
}

// 重置上次发送时间_dtSend
void CELLClient::resetDtSend()
{
	_dtSend = 0;
}

// 心跳检测，返回真代表本客户端挂了
bool CELLClient::checkHeart(time_t dt)
{
	_dtHeart += dt;
	if (_dtHeart >= CLIENT_HEART_DEAD_TIME)
	{
		CELLLog_Info("chackHeart dead: %d, time: %d", _sockfd, _dtHeart);
		return true;
	}
	return false;
}

// 定时发送消息检测
bool CELLClient::checkSend(time_t dt)
{
	_dtSend += dt;
	if (_dtSend >= CLIENT_SEND_BUF_TIME)
	{
		// CELLLog_Info("超时发送");
		// 立即将缓冲区数据发送出去
		SendDataReal();
		// 重置上次发送数据时间(上一行函数里也重置了，防止其它函数调用它时没有重置)
		resetDtSend();
	}
	return false;
}
